%     AERO LOAD - программа для нагружения агрегатов самолета распределенной нагрузкой
%     Copyright (C) 2018  Михаил Козлов
%     Сайт проекта: <http://www.fastenerdoctor.ru/>
%     Адрес электронной почты для связи с разработчиком:
%     <doctor.fastener@gmail.com>
% 
%     Эта программа является свободным программным обеспечением: Вы можете
%     распространять ее и/или изменять, соблюдая условия Универсальной общественной
%     лицензии GNU, опубликованной Фондом свободного программного обеспечения,
%     либо редакции 3, либо (на Ваше усмотрение) любой редакции, выпущенной позже.
% 
%     Эта программа распространяется в надежде на то, что она окажется полезной,
%     но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, включая даже подразумеваемую гарантию ТОВАРНОЙ ПРИГОДНОСТИ,
%     либо ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Ознакомьтесь с Универсальной общественной
%     лицензией GNU для получения более подробной информации.
% 
%     Вы должны были получить копию Универсальной общественной лицензии GNU
%     вместе с этой программой. Если Вы ее не получили, то перейдите по адресу:
%     <http://www.gnu.org/licenses/>.
% 
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
% 
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%     GNU General Public License for more details.
% 
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <https://www.gnu.org/licenses/>.

function [Read_Result, Fin, ...
          Previous_index, Record_length, Next_string_large, Record_read_counter, End_card_flag, ...
          string, Previous_strings] = ...
                                                                             Read_Field_I ...
          (Fin_inp, Card_name, Item_ID, ...
           Previous_index_inp, Record_length_inp, Next_string_large_inp, Record_read_counter_inp, End_card_flag_inp, ...
           string_inp, Previous_strings_inp)

% Функция чтения опционального поля (INTEGER)

% Коды ошибок:
% ErrCode = -1 | общие ошибки (с печатью сообщения об ошибке)
% ErrCode = -2 | пустое поле
% ErrCode = -3 | неправильный формат поля
       
global ErrCode;
       
Read_Result = [];

Fin = Fin_inp;

Previous_index = Previous_index_inp;
Record_length = Record_length_inp;
Next_string_large = Next_string_large_inp;
Record_read_counter = Record_read_counter_inp; % Отсчет прочтенных полей начинается со второго поля карточки
End_card_flag = End_card_flag_inp;

string = string_inp;
Previous_strings = Previous_strings_inp;

% --- Единичное чтение, поле опциональное (INTEGER) ---

% Чтение поля
if (End_card_flag ~= 1)

    % Расчет теоретических индексов
    Start_index = Previous_index + 1;
    End_index = Previous_index + Record_length;

    % Чтение INTEGER, поле опциональное
    if (length(Trim_CR_LF(string)) > Previous_index)
        if (length(string) < End_index)
            End_index = length(string);
        end
        % Возврат в случае пустого поля
        if (isempty(strtrim(string(Start_index:End_index))))
            ErrCode = -2;
            return;
        end
        % Возврат в случае неправильного формата поля
        if (isnan(str2double(string(Start_index:End_index))))
            ErrCode = -3;
            return;
        end
        Read_Result = str2double(string(Start_index:End_index));
    end
    
    % Обновление счетчика
    Record_read_counter = Record_read_counter + 1;
    
    % Обновление последнего индекса (присвоение теоретического значения)
    Previous_index = Previous_index + Record_length;
    
    % Если дошли до конца строки, то читаем новую строку и обновляем параметры
    if (Record_read_counter == 64/Record_length)
        
        % Если конец файла, то это конец карточки
        if (feof(Fin))
            End_card_flag = 1;
        end
            
        if (End_card_flag ~= 1)
            
            % Чтение следующей строки с бэкапом
            N_prev_str = size(Previous_strings,1);
            string_backup = Previous_strings{N_prev_str};
            for p=1:N_prev_str-1
                Previous_strings{N_prev_str+1-p} = Previous_strings{N_prev_str-p};
            end
            Previous_strings{1} = string;
            string = fgets(Fin);

            % Проверка парности строк с идентификатором *
            if ((Next_string_large == 1) && (string(1) ~= '*'))
                fprintf (1, '\nНепарная строка с идентификатором * в карточке %s с номером %i !\n', Card_name, Item_ID);
                ErrCode = -1;
                return;
            end

            % Проверка первого символа
            if (~((string(1) == '*') || (string(1) == ' ') || (string(1) == '+')))

                % Откат назад
                fseek(Fin, -length(string), 'cof');
                N_prev_str = size(Previous_strings,1);
                string = Previous_strings{1};
                for p=1:N_prev_str-1
                    Previous_strings{p} = Previous_strings{p+1};
                end
                Previous_strings{N_prev_str} = string_backup;

                End_card_flag = 1; % конец карточки

            end
            
            if (End_card_flag ~= 1)
                % Проверка на записи в 10-ом поле
                if (deblank(string) > 72)
                    fprintf (1, '\nОбнаружена запись в поле 10 карточки %s с номером %i !\n', Card_name, Item_ID);
                    fprintf (1, 'Указатели продления карточки не поддерживаются в текущей версии программы.\n');
                    fprintf (1, 'Обратетись к разработчику для решения этого вопроса.\n');
                    ErrCode = -1;
                    return;
                end
            end

            if (End_card_flag ~= 1)
                % Строка только из белых символов
                if (isempty(strtrim(string)))
                    End_card_flag = 1; % конец карточки
                end
            end

            if (End_card_flag ~= 1)

                % Установка параметров
                switch string(1)

                    case ' '
                        Previous_index = 8;
                        Record_length = 8;
                        Next_string_large = 0;
                        Record_read_counter = 0;
                        
                    case '+'
                        Previous_index = 8;
                        Record_length = 8;
                        Next_string_large = 0;
                        Record_read_counter = 0;

                    case '*'
                        Previous_index = 8;
                        Record_length = 16;
                        Next_string_large = 1 - Next_string_large;
                        Record_read_counter = 0;

                end
            end
        end
    end
end
